package http

import "C"
import (
	"fmt"
	"gateway"
	"io/ioutil"
	"net/http"
	"net/url"
	"runtime"
	"strings"
)

type Http11Server struct {
	Config gateway.Config
}

func GetHttp11Server(config gateway.Config) Http11Server {
	return Http11Server{Config: config}
}

func (server Http11Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	path, para := prepareQueryString(req.URL)
	header := converHeader(para)
	method := req.Method
	if method != "GET" && method != "POST" {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	if method == "POST" {
		if req.Body == nil {
			http.Error(w, "empty body", http.StatusBadRequest)
			return
		}
	}
	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		http.Error(w, "cannot read body", http.StatusBadRequest)
		return
	}
	loginip := strings.Split(req.RemoteAddr, ":")[0]
	if loginip == "" {
		loginip = "0.0.0.0"
	}
	context := BuildContext(path, method, header, body, loginip)
	Http11Handler := NewHttp11Handler(context)
	Http11Handler.Call()
}

func converHeader(header map[string][]string) map[string]string {

	response := make(map[string]string, 0)
	if len(header) == 0 {
		return response
	}

	for key, value := range header {
		response[key] = value[0]
	}

	return response

}

func prepareQueryString(route *url.URL) (string, map[string][]string) {

	if route == nil {
		//panic(NewError("route is nil"))
	}

	rawQuery, err := url.QueryUnescape(route.RawQuery)

	if err != nil {
		//panic(NewError("rawQuery parse err"))
	}

	var params = make(map[string][]string)

	values, err := url.ParseQuery(rawQuery)
	if err != nil {
		//panic(NewError(err.Error()))
	}
	for key, value := range values {
		params[key] = value
	}

	return strings.ToLower(route.Path), params
}

func (server Http11Server) Start() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	fmt.Println("listening .....:", server.Config.Http11Port)
	http.ListenAndServe(fmt.Sprintf(":%d", server.Config.Http11Port), &server)
}

func (server Http11Server) Stop() {

}
